home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DDJMAG
/
DDJ9212.ZIP
/
cprog.asc
< prev
next >
Wrap
Text File
|
1992-11-30
|
15KB
|
635 lines
_C PROGRAMMING COLUMN_
by Al Stevens
[LISTING ONE]
// --------------- desktop.cpp
#include <new.h>
#include "desktop.h"
DeskTop desktop;
#ifdef MSC
int NoMemory(unsigned int)
{
exit(-1);
return 0;
}
#else
void NoMemory()
{
exit(-1);
}
#endif
DeskTop::DeskTop()
{
apwnd = infocus = firstcapture = focuscapture = NULL;
#ifdef MSC
_set_new_handler(&NoMemory);
#else
set_new_handler(NoMemory);
#endif
syscursor.Hide();
}
DeskTop::~DeskTop()
{
syscursor.Show();
}
Bool DeskTop::DispatchEvents()
{
syskeyboard.DispatchEvent();
sysmouse.DispatchEvent();
sysclock.DispatchEvent();
return (Bool) (apwnd != NULL);
}
[LISTING TWO]
// ----------- screen.cpp
#include <string.h>
#include "desktop.h"
Screen::Screen()
{
if (isEGA() || isVGA()) {
// --- turn blinking off
regs.x.ax = 0x1003;
regs.h.bl = 0;
int86(VIDEO, ®s, ®s);
}
// ---- get the video mode and page
regs.h.ah = 15;
int86(VIDEO, ®s, ®s);
mode = regs.h.al;
page = regs.x.bx;
page &= 0xff00;
mode &= 0x7f;
// ---- Monochrome Display Adaptor or text mode
if (isMono())
address = 0xb000;
else
// ------ Text mode
address = 0xb800 + page;
width = *(unsigned char far *)( MK_FP(0x40,0x4a) );
if (isVGA() || isEGA())
height = *(unsigned char far *)( MK_FP(0x40,0x84) )+1;
else
height = 25;
}
// ---- test for EGA
Bool Screen::isEGA(void)
{
if (isVGA())
return False;
regs.h.ah = 0x12;
regs.h.bl = 0x10;
int86(VIDEO, ®s, ®s);
return (Bool) (regs.h.bl != 0x10);
}
// ---- test for VGA
Bool Screen::isVGA(void)
{
regs.x.ax = 0x1a00;
int86(VIDEO, ®s, ®s);
return (Bool) (regs.h.al == 0x1a && regs.h.bl > 6);
}
// --------- scroll the screen d: 1 = up, 0 = dn
void Screen::Scroll(Rect &rc, int d, int fg, int bg)
{
desktop.mouse().Hide();
regs.h.cl = rc.Left();
regs.h.ch = rc.Top();
regs.h.dl = rc.Right();
regs.h.dh = rc.Bottom();
regs.h.bh = clr(fg,bg);
regs.h.ah = 7 - d;
regs.h.al = 1;
int86(VIDEO, ®s, ®s);
desktop.mouse().Show();
}
// -------- read a character of video memory
unsigned int Screen::GetVideoChar(int x, int y)
{
int c;
desktop.mouse().Hide();
c = peek(address, vad(x,y));
desktop.mouse().Show();
return c & 255;
}
// -------- write a character of video memory
void Screen::PutVideoChar(int x, int y, unsigned int c)
{
if (x < width && y < height) {
desktop.mouse().Hide();
poke(address, vad(x,y), c);
desktop.mouse().Show();
}
}
// --------- Write a string to video memory
void Screen::WriteVideoString(char *s,int x,int y,int fg,int bg)
{
if (x < width && y < height) {
int len = strlen(s);
int *ln = new int[len];
int *cp1 = ln;
int col = clr(fg,bg) << 8;
while (*s) {
*cp1++ = (*s & 255) | col;
s++;
}
if (x + len >= width)
len = width - x;
desktop.mouse().Hide();
movedata(FP_SEG(ln),FP_OFF(ln),address,vad(x,y),len*2);
desktop.mouse().Show();
delete [] ln;
}
}
// -- read a rectangle of video memory into a save buffer
void Screen::GetBuffer(Rect &rc, char *bf)
{
if (rc.Left() >= width || rc.Top() >= height)
return;
int ht = rc.Bottom()-rc.Top()+1;
int bytes_row = (rc.Right()-rc.Left()+1) * 2;
unsigned vadr = vad(rc.Left(), rc.Top());
desktop.mouse().Hide();
while (ht--) {
movedata(address, vadr, FP_SEG(bf),
FP_OFF(bf), bytes_row);
vadr += width*2;
bf = (char far *)bf + bytes_row;
}
desktop.mouse().Show();
}
// -- write a rectangle of video memory from a save buffer
void Screen::PutBuffer(Rect &rc, char *bf)
{
if (rc.Left() >= width || rc.Top() >= height)
return;
int ht = rc.Bottom()-rc.Top()+1;
int bytes_row = (rc.Right()-rc.Left()+1) * 2;
unsigned vadr = vad(rc.Left(), rc.Top());
desktop.mouse().Hide();
while (ht--) {
movedata(FP_SEG(bf), FP_OFF(bf), address,
vadr, bytes_row);
vadr += width*2;
bf += bytes_row;
}
desktop.mouse().Show();
}
[LISTING THREE]
// ------------- mouse.cpp
#include <stdio.h>
#include "desktop.h"
// -------- mouse constructor
Mouse::Mouse()
{
// ------- see if mouse driver is installed
unsigned char far *ms;
ms = (unsigned char far *)
MK_FP(peek(0, MOUSE*4+2), peek(0, MOUSE*4));
// --- if the interrupt vector is null or points to a retf,
// the mouse driver is not installed
installed = (Bool) (ms != NULL && *ms != 0xcf);
if (installed) {
// --- get the mouse state buffer size
CallMouse(BUFFSIZE);
statebuffer = new char[regs.x.bx];
// --- save the mouse state
CallMouse(SAVESTATE, 0, 0,
FP_OFF(statebuffer), FP_SEG(statebuffer));
// --- reset the mouse
CallMouse(RESETMOUSE);
prevx = prevy =
clickx = clicky =
releasex = releasey -1;
SetTravel(0, desktop.screen().Width()-1, 0,
desktop.screen().Height()-1);
}
}
Mouse::~Mouse()
{
if (installed) {
Hide();
// --- restore the mouse state
CallMouse(RESTORESTATE, 0, 0,
FP_OFF(statebuffer), FP_SEG(statebuffer));
delete [] statebuffer;
}
}
void Mouse::GetPosition(int &mx, int &my)
{
mx = my = 0;
if (installed) {
CallMouse(READMOUSE);
mx = regs.x.cx/8;
my = regs.x.dx/8;
if (desktop.screen().Width() == 40)
mx /= 2;
}
}
void Mouse::SetPosition(int x, int y)
{
if (installed) {
if (desktop.screen().Width() == 40)
x *= 2;
CallMouse(SETPOSITION,0,x*8,y*8);
}
}
Bool Mouse::Moved()
{
int x, y;
Bool rtn = False;
if (installed) {
GetPosition(x, y);
rtn = (Bool) (x != prevx || y != prevy);
prevx = x;
prevy = y;
}
return rtn;
}
void Mouse::Show()
{
if (installed)
CallMouse(SHOWMOUSE);
}
void Mouse::Hide()
{
if (installed)
CallMouse(HIDEMOUSE);
}
Bool Mouse::LeftButton()
{
Bool rtn = False;
if (installed) {
CallMouse(READMOUSE);
rtn = (Bool) ((regs.x.bx & 1) == 1);
}
return rtn;
}
Bool Mouse::ButtonReleased()
{
Bool rtn = False;
if (installed) {
CallMouse(BUTTONRELEASED);
rtn = (Bool) (regs.x.bx != 0);
}
return rtn;
}
void Mouse::SetTravel(int minx, int maxx, int miny, int maxy)
{
if (installed) {
if (desktop.screen().Width() == 40) {
minx *= 2;
maxx *= 2;
}
CallMouse(XLIMIT, 0, minx*8, maxx*8);
CallMouse(YLIMIT, 0, miny*8, maxy*8);
}
}
void Mouse::CallMouse(int m1,int m2,int m3,int m4, unsigned es)
{
struct SREGS sregs;
segread(&sregs);
if (es != 0)
sregs.es = es;
regs.x.dx = m4;
regs.x.cx = m3;
regs.x.bx = m2;
regs.x.ax = m1;
int86x(MOUSE, ®s, ®s, &sregs);
}
// ------ get the window to send mouse events
DFWindow *Mouse::MouseWindow(int mx, int my)
{
DFWindow *Mwnd;
if (desktop.FocusCapture() != NULL)
Mwnd = desktop.FocusCapture();
else
Mwnd = inWindow(mx, my);
return Mwnd;
}
void Mouse::DispatchRelease()
{
if (ButtonReleased()) {
int mx, my;
GetPosition(mx, my);
DFWindow *Mwnd;
if ((Mwnd = MouseWindow(mx, my)) == NULL)
return;
// ------- disable typematic check
clickx = clicky = -1;
delaytimer.DisableTimer();
// ------- the button was released
if (mx == releasex && my == releasey) {
// ---- same position as last left button release
if (doubletimer.TimerRunning()) {
// -- second click before double timeout
doubletimer.DisableTimer();
Mwnd->DoubleClick(mx, my);
releasex = releasey = -1;
}
}
else {
doubletimer.SetTimer(DOUBLETICKS);
Mwnd->ButtonReleased(mx, my);
releasex = mx;
releasey = my;
}
}
}
void Mouse::DispatchMove()
{
if (Moved()) {
int mx, my;
GetPosition(mx, my);
DFWindow *Mwnd;
if ((Mwnd = MouseWindow(mx, my)) != NULL) {
Mwnd->MouseMoved(mx, my);
clickx = clicky = -1;
}
}
}
void Mouse::DispatchLeftButton()
{
if (LeftButton()) {
int mx, my;
GetPosition(mx, my);
DFWindow *Mwnd;
if ((Mwnd = MouseWindow(mx, my)) == NULL)
return;
if (mx == clickx && my == clicky) {
if (delaytimer.TimedOut()) {
// ---- button held down a while
delaytimer.SetTimer(DELAYTICKS);
// ---- post a typematic-like button
Mwnd->LeftButton(mx, my);
}
}
else {
// --------- new button press
delaytimer.SetTimer(FIRSTDELAY);
if (Mwnd->SetFocus())
Mwnd->LeftButton(mx, my);
clickx = mx;
clicky = my;
}
}
}
// -------- dispatch mouse events
void Mouse::DispatchEvent()
{
DispatchRelease();
DispatchMove();
DispatchLeftButton();
}
[LISTING FOUR]
// ------------ cursor.cpp
#include <dos.h>
#include "cursor.h"
#include "desktop.h"
Cursor::Cursor()
{
cs = 0;
Save();
}
Cursor::~Cursor()
{
Restore();
}
// ------ get cursor shape and position
void Cursor::GetCursor()
{
regs.h.ah = READCURSOR;
regs.x.bx = desktop.screen().Page();
int86(VIDEO, ®s, ®s);
}
// -------- get the current cursor position
void Cursor::GetPosition(int &x, int &y)
{
GetCursor();
x = regs.h.dl;
y = regs.h.dh;
}
// ------ position the cursor
void Cursor::SetPosition(int x, int y)
{
regs.x.dx = ((y << 8) & 0xff00) + x;
regs.h.ah = SETCURSOR;
regs.x.bx = desktop.screen().Page();
int86(VIDEO, ®s, ®s);
}
// ------ save the current cursor configuration
void Cursor::Save()
{
if (cs < MAXSAVES) {
GetCursor();
cursorshape[cs] = regs.x.cx;
cursorpos[cs] = regs.x.dx;
cs++;
}
}
// ---- restore the saved cursor configuration
void Cursor::Restore()
{
if (cs) {
--cs;
regs.x.dx = cursorpos[cs];
regs.h.ah = SETCURSOR;
regs.x.bx = desktop.screen().Page();
int86(VIDEO, ®s, ®s);
SetType(cursorshape[cs]);
}
}
/* ---- set the cursor type ---- */
void Cursor::SetType(unsigned t)
{
regs.h.ah = SETCURSORTYPE;
regs.x.bx = desktop.screen().Page();
regs.x.cx = t;
int86(VIDEO, ®s, ®s);
}
/* ----- swap the cursor stack ------- */
void Cursor::SwapStack()
{
if (cs > 1) {
swap(cursorpos[cs-2], cursorpos[cs-1]);
swap(cursorshape[cs-2], cursorshape[cs-1]);
}
}
/* ------ hide the cursor ------ */
void Cursor::Hide()
{
GetCursor();
regs.h.ch |= HIDECURSOR;
regs.h.ah = SETCURSORTYPE;
int86(VIDEO, ®s, ®s);
}
/* ------ show the cursor ------ */
void Cursor::Show()
{
GetCursor();
regs.h.ch &= ~HIDECURSOR;
regs.h.ah = SETCURSORTYPE;
int86(VIDEO, ®s, ®s);
}
[LISTING FIVE]
// ----------- keyboard.cpp
#include <stdio.h>
#include <bios.h>
#include <dos.h>
#include "desktop.h"
/* ----- table of alt keys for finding shortcut keys ----- */
static int altconvert[] = {
ALT_A,ALT_B,ALT_C,ALT_D,ALT_E,ALT_F,ALT_G,ALT_H,
ALT_I,ALT_J,ALT_K,ALT_L,ALT_M,ALT_N,ALT_O,ALT_P,
ALT_Q,ALT_R,ALT_S,ALT_T,ALT_U,ALT_V,ALT_W,ALT_X,
ALT_Y,ALT_Z,ALT_0,ALT_1,ALT_2,ALT_3,ALT_4,ALT_5,
ALT_6,ALT_7,ALT_8,ALT_9
};
/* ---- Test for keystroke ---- */
#ifndef MSC
Bool Keyboard::KeyHit()
{
_AH = 1;
geninterrupt(KEYBRD);
return (Bool)((_FLAGS & ZEROFLAG) == 0);
}
#else
Bool Keyboard::KeyHit()
{
return (Bool) (bioskey(1) != 0);
}
#endif
/* ---- Read a keystroke ---- */
int Keyboard::GetKey()
{
int c;
while (KeyHit() == False)
;
if (((c = bioskey(0)) & 0xff) == 0)
c = (c >> 8) | 0x1080;
else
c &= 0xff;
return c & 0x10ff;
}
/* ---------- read the keyboard shift status --------- */
int Keyboard::GetShift()
{
regs.h.ah = 2;
int86(KEYBRD, ®s, ®s);
return regs.h.al;
}
/* ------ convert an Alt+ key to its letter equivalent ----- */
int Keyboard::AltConvert(int c)
{
int i, a = 0;
for (i = 0; i < 36; i++)
if (c == altconvert[i])
break;
if (i < 26)
a = 'a' + i;
else if (i < 36)
a = '0' + i - 26;
return a;
}
Bool Keyboard::ShiftChanged()
{
int sk = GetShift();
Bool rtn = (Bool) (sk != shift);
shift = sk;
return rtn;
}
// ------ dispatch keyboard events
void Keyboard::DispatchEvent()
{
// ---- find window for keyboard events
DFWindow *Kwnd = desktop.FocusCapture() ?
desktop.FocusCapture() :
desktop.InFocus() ?
desktop.InFocus() : desktop.ApplWnd();
if (ShiftChanged())
// ---- the shift status changed
Kwnd->ShiftChanged(GetShift());
if (KeyHit())
// --- a key was pressed
Kwnd->Keyboard(GetKey());
}
[LISTING SIX]
// -------- speaker.cpp
#include <dos.h>
#include <conio.h>
#include "speaker.h"
#include "dflatdef.h"
// -------- sound a tone
void Speaker::Beep()
{
outp(0x43, 0xb6); // program the frequency
outp(0x42, (int) (COUNT % 256));
outp(0x42, (int) (COUNT / 256));
outp(0x61, inp(0x61) | 3); // start the sound
// -------- wait two clock ticks
const int far *clk = (int far *) MK_FP(0x40,0x6c);
int then = *clk+2;
while (*clk < then)
;
outp(0x61, inp(0x61) & ~3); // stop the sound
}
[LISTING SEVEN]
// ------- clock.cpp
#include "desktop.h"
Clock::Clock()
{
clocktimer.SetTimer(0);
}
void Clock::DispatchEvent()
{
if (clocktimer.TimedOut()) {
// -------- reset the timer
clocktimer.SetTimer(19); // approx. 19 tics/second
// -------- post the clock event
if (desktop.ApplWnd() != NULL)
desktop.ApplWnd()->ClockTick();
}
}